package com.xf.auth.configure;


import cn.binarywang.wx.miniapp.api.WxMaService;
import com.xf.auth.extension.mobile.SmsCodeAuthenticationProvider;
import com.xf.auth.extension.wechat.WechatAuthenticationProvider;
import com.xf.auth.handler.FebsWebLoginFailureHandler;
import com.xf.auth.handler.FebsWebLoginSuccessHandler;
import com.xf.common.security.starter.handler.FebsAuthExceptionEntryPoint;
import com.xf.common.security.starter.handler.LoginFormAuthExceptionEntryPoint;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * WebSecurity配置
 * 即是授权服务器,也是资源服务器.
 *
 * @author xufeng
 */
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfigure extends WebSecurityConfigurerAdapter {

    private final UserDetailsService sysUserDetailService;
    private final PasswordEncoder passwordEncoder;
    private final FebsWebLoginSuccessHandler successHandler;
    private final FebsWebLoginFailureHandler failureHandler;
    private final UserDetailsService memberUserDetailsService;
    private final WxMaService wxMaService;
    private final StringRedisTemplate redisTemplate;
    private final FebsAuthExceptionEntryPoint febsAuthExceptionEntryPoint;
    /**
     * 认证管理对象
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                //表单登录的异常翻译
                .exceptionHandling().authenticationEntryPoint(new LoginFormAuthExceptionEntryPoint())
                .and()
                .authorizeRequests()
                //不需要登录的地址
                .antMatchers( "/login", "/src/main/resources/**", "/static/**","/auth/user/register*").permitAll()
                .anyRequest().authenticated()// 任何请求 都需要身份认证
                .and()
                .formLogin().successHandler(successHandler).failureHandler(failureHandler)
                //关闭基础表单认证
                .and().httpBasic().disable();
}

    /**
     * 手机验证码认证授权提供者
     *
     * @return
     */
    @Bean
    public SmsCodeAuthenticationProvider smsCodeAuthenticationProvider() {
        SmsCodeAuthenticationProvider provider = new SmsCodeAuthenticationProvider();
        provider.setUserDetailsService(memberUserDetailsService);
        provider.setRedisTemplate(redisTemplate);
        return provider;
    }

    /**
     * 微信认证授权提供者
     *
     * @return
     */
    @Bean
    public WechatAuthenticationProvider wechatAuthenticationProvider() {
        WechatAuthenticationProvider provider = new WechatAuthenticationProvider();
        provider.setUserDetailsService(memberUserDetailsService);
        provider.setWxMaService(wxMaService);
        return provider;
    }


    /**
     * 用户名密码认证授权提供者
     *
     * @return
     */
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(sysUserDetailService);
        provider.setPasswordEncoder(passwordEncoder);
        // 是否隐藏用户不存在异常，默认:true-隐藏；false-抛出异常；
        provider.setHideUserNotFoundExceptions(false);
        return provider;
    }

    /**
     * 认证管理器
     * @param auth
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(wechatAuthenticationProvider()).
                authenticationProvider(daoAuthenticationProvider()).
                authenticationProvider(smsCodeAuthenticationProvider());
    }


}
